package ssh

import (
	"fmt"
	"kubeInstall/pkg/logger"
	"os"
	"os/exec"
	"strconv"
	"strings"
)

const oneKBByte = 1024
const oneMBByte = 1024 * 1024

func (ss *SSH) CopyForMD5(localFilePath, remoteFilePath, md5 string) bool {
	if md5 == "" {
		md5 = FromLocal(localFilePath)
	}
	logger.Debug("[ssh]source file md5 value is %s", md5)
	ss.Copy(localFilePath, remoteFilePath)
	remoteMD5 := ss.Md5Sum(remoteFilePath)
	logger.Debug("[ssh]host: %s , remote md5: %s", ss.HostIp, remoteMD5)
	remoteMD5 = strings.TrimSpace(remoteMD5)
	md5 = strings.TrimSpace(md5)
	if remoteMD5 == md5 {
		logger.Info("[ssh]md5 validate true")
		return true
	}
	logger.Error("[ssh]md5 validate false")
	return false
}

func (ss *SSH) Md5Sum(remoteFilePath string) string {
	cmd := fmt.Sprintf("md5sum %s | cut -d\" \" -f1", remoteFilePath)
	remoteMD5, _ := ss.CmdToString(cmd, "")
	return remoteMD5
}

//Copy is
func (ss *SSH) Copy(localFilePath, remoteFilePath string) {

	srcFile, err := os.Open(localFilePath)
	defer func() {
		if r := recover(); r != nil {
			logger.Error("[ssh][%s][scpCopy] open file failed: %s", ss.HostIp, err)
		}
	}()
	if err != nil {
		panic(1)
	}
	defer srcFile.Close()

	dstFile, err := ss.SftpClient.Create(remoteFilePath)
	defer func() {
		if r := recover(); r != nil {
			logger.Error("[ssh][%s][scpCopy] create remote file %s failed: %s", ss.HostIp, dstFile.Name(), err)
		}
	}()
	if err != nil {
		panic(1)
	}
	defer dstFile.Close()
	buf := make([]byte, 100*oneMBByte) //100mb
	total := 0
	unit := ""
	for {
		n, _ := srcFile.Read(buf)
		if n == 0 {
			break
		}
		length, _ := dstFile.Write(buf[0:n])
		isKb := length/oneMBByte < 1
		speed := 0
		if isKb {
			total += length
			unit = "KB"
			speed = length / oneKBByte
		} else {
			total += length
			unit = "MB"
			speed = length / oneMBByte
		}
		totalLength, totalUnit := toSizeFromInt(total)
		logger.Info("[ssh][%s]transfer total size is: %.2f%s ;speed is %d%s", ss.HostIp, totalLength, totalUnit, speed, unit)
	}
}

func toSizeFromInt(length int) (float64, string) {
	isMb := length/oneMBByte > 1
	value, _ := strconv.ParseFloat(fmt.Sprintf("%.2f", float64(length)/oneMBByte), 64)
	if isMb {
		return value, "MB"
	} else {
		value, _ = strconv.ParseFloat(fmt.Sprintf("%.2f", float64(length)/oneKBByte), 64)
		return value, "KB"
	}
}
func FromLocal(localPath string) string {
	cmd := fmt.Sprintf("md5sum %s | cut -d\" \" -f1", localPath)
	c := exec.Command("sh", "-c", cmd)
	out, err := c.CombinedOutput()
	if err != nil {
		logger.Error(err)
	}
	md5 := string(out)
	md5 = strings.ReplaceAll(md5, "\n", "")
	md5 = strings.ReplaceAll(md5, "\r", "")

	return md5
}
